package jp.androidgroup.chiba.androidresearch.ui;

import java.util.ArrayList;
import java.util.List;

import jp.androidgroup.chiba.androidresearch.Common;
import jp.androidgroup.chiba.androidresearch.Constants;
import jp.androidgroup.chiba.androidresearch.R;
import jp.androidgroup.chiba.androidresearch.UserInfo;
import jp.androidgroup.chiba.androidresearch.aws.Sdb;
import jp.androidgroup.chiba.androidresearch.data.Base;
import jp.androidgroup.chiba.androidresearch.data.MasterVersion;
import jp.androidgroup.chiba.androidresearch.data.Occupation;
import jp.androidgroup.chiba.androidresearch.data.Place;
import jp.androidgroup.chiba.androidresearch.data.Time;
import jp.androidgroup.chiba.androidresearch.data.Use;
import jp.androidgroup.chiba.androidresearch.db.DatabaseHelper;
import jp.androidgroup.chiba.androidresearch.oauth.PrepareRequestTokenActivity;
import jp.androidgroup.chiba.androidresearch.oauth.SharedPreferencesManager;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

/**
 * TOP画面です。
 * SQLiteに登録済みで、SDBにアップできていない投稿データが存在する場合にリストで表示します。
 */
public final class CounterActivity extends Activity implements AdapterView.OnItemClickListener {

	/**
	 * CounterEditActivityに渡す日付のパラメーター
	 */
	public static final String EXTRA_DATE = "AndroidResearch.CounterActivity.Date";
	/**
	 * CounterEditActivityに渡す時間のパラメーター
	 */
	public static final String EXTRA_TIME = "AndroidResearch.CounterActivity.Time";
	/**
	 * CounterEditActivityに渡す場所のパラメーター
	 */
	public static final String EXTRA_PLACE = "AndroidResearch.CounterActivity.Place";
	/**
	 * CounterEditActivityに渡す場所のパラメーター
	 */
	public static final String EXTRA_MEMO = "AndroidResearch.CounterActivity.Memo";


	private static final int REQUEST_ADD = 1;


	//SQLite
	private DatabaseHelper mDatabase;
	private SQLiteDatabase mdb;
	private Cursor mcur;
	private SharedPreferences mPref;
	private ListView mListView;
	private TextView mEmptyText;
	private CounterAdapter mAdapter;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_counter);

		mDatabase = new DatabaseHelper(this); //ヘルパークラスのインスタンスを作成
		 // リストビュー取得
        mListView = (ListView) findViewById(R.id.list);
        mListView.setOnItemClickListener(CounterActivity.this);
        // 空時のテキスト取得
        mEmptyText = (TextView) findViewById(R.id.emptytext);

        mPref = getPreferences(MODE_PRIVATE);

		// SDBから情報取得
		new SdbTask().execute();
	}

	@Override
	protected void onResume() {
		super.onResume();

		// DBサンプル
		mdb = mDatabase.getWritableDatabase();

		// ユーザの認証を通っていない場合は、認証処理を行います。
		SharedPreferencesManager spm = new SharedPreferencesManager(this);
		UserInfo userInfo = spm.getUserInfo();
		// staticでUserInfo情報を保持するために設定
		Common.setUserInfo(userInfo);

		// 認証が完了していない場合、認証処理を促します。
		if (userInfo.getId() == null || userInfo.getId().length() == 0) {
			AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);
			alertDialog.setTitle("確認メッセージ");
			alertDialog
					.setMessage("Googleアカウントの認証をお願いします。\n認証する場合は「はい」を選択して処理を続行して下さい。\n認証しない場合は「いいえ」を選択し、アプリを終了して下さい。");
			alertDialog.setPositiveButton("はい", authDialogListner);
			alertDialog.setNegativeButton("いいえ", authDialogListner);
			alertDialog.create();
			alertDialog.show();
		}
	}

	/*
	 * メニューの作成
	 * (non-Javadoc)
	 * @see android.app.Activity#onCreateOptionsMenu(android.view.Menu)
	 */
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.counter_activity, menu);
		return true;
	}

	/*
	 * メニュークリック時
	 * (non-Javadoc)
	 * @see android.app.Activity#onOptionsItemSelected(android.view.MenuItem)
	 */
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {

		Intent intent;

		switch (item.getItemId()) {
		case R.id.menuitem_add: // 追加
			intent = new Intent(this, CounterAddActivity.class);
			startActivityForResult(intent, REQUEST_ADD);
			return true;

		case R.id.menuitem_log: // ログ
			intent = new Intent(this, CounterLogActivity.class);
			startActivity(intent);
			return true;
		}
		return false;
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
		if (requestCode == REQUEST_ADD) {
			if (resultCode == RESULT_OK) {
				createListFromDB();
			}
		}
	}

	/*
	 * リストアイテムクリック時
	 * (non-Javadoc)
	 * @see android.widget.AdapterView.OnItemClickListener#onItemClick(android.widget.AdapterView, android.view.View, int, long)
	 */
	public void onItemClick(AdapterView<?> parent, View view, final int position, long id) {
		final BindData data = (BindData) parent.getItemAtPosition(position);

		// 編集・削除ダイアログの表示
		new AlertDialog.Builder(this)
		.setItems(R.array.counter_list_detail, new DialogInterface.OnClickListener() {

			public void onClick(DialogInterface dialog, int which) {
				// 編集
				if (which == 0) {
					// 編集画面へ
					Intent intent = new Intent(CounterActivity.this, CounterEditActivity.class);
					// 編集画面に対しパラメーターを渡す
					intent.putExtra(EXTRA_DATE, data.date);
					intent.putExtra(EXTRA_TIME, data.time);
					intent.putExtra(EXTRA_PLACE, data.place);
					intent.putExtra(EXTRA_MEMO, data.memo);
					startActivity(intent);
				}
				// 削除
				// ダイアログを表示して削除確認
				else if (which == 1) {
					showDialogDeleteEntry(position);
				}
			}
		})
		.create().show();
	}

	/**
	 * 集計の削除確認ダイアログ
	 */
	private void showDialogDeleteEntry(final int position) {

		new AlertDialog.Builder(this)
		.setIcon(android.R.drawable.ic_dialog_alert)
		.setTitle(R.string.l_delete_confirmation)
		.setMessage(R.string.m_entry_delete)
		.setPositiveButton(R.string.l_del, new DialogInterface.OnClickListener() {

			public void onClick(DialogInterface dialog, int which) {
				SQLiteDatabase db;
				try {
					db = mDatabase.getWritableDatabase();
				} catch (SQLiteException e) {
					e.printStackTrace();
					Toast.makeText(CounterActivity.this, e.getMessage(), Toast.LENGTH_LONG).show();
					return;
				}


				BindData data = mAdapter.getItem(position);
				final String whereClause = "ContributeDate=? AND " +
						"PlaceId=? AND TimeId=? AND Memo=? AND UploadDate IS NULL";
				final String[] whereArgs = { data.date, data.place, data.time, data.memo };

				db.beginTransaction();
				try {
					int rows = db.delete("Counter", whereClause, whereArgs);
					Log.d("CounterActivity", "Delete rows from database: " + rows);
					db.setTransactionSuccessful();
				} catch (IllegalStateException e) {
					e.printStackTrace();
					Toast.makeText(CounterActivity.this, e.getMessage(), Toast.LENGTH_LONG).show();
					return;
				} finally {
					db.endTransaction();
				}

				mAdapter.removeItem(position);
				mAdapter.notifyDataSetChanged();

				// 集計が0の場合、EmptyTextの表示
				if (mAdapter.getCount() == 0) {
					mEmptyText.setVisibility(View.VISIBLE);
				}
			}
		})
		.setNegativeButton(R.string.l_cancel, (DialogInterface.OnClickListener) null)
		.create().show();
	}

	/**
	 * 内部DBから自分の集計履歴を取得してListViewに表示する
	 */
	private void createListFromDB() {
		//SQLite
//		mdb = mDatabase.getReadableDatabase(); //ヘルパークラスのgetReadableDatabase()メソッドを呼び出し、データベースオブジェクトを取得

		String sqlstr = "SELECT ContributeDate, PlaceId, TimeId, Memo FROM Counter " +
				"WHERE UploadDate IS NULL " +
				"GROUP BY ContributeDate, PlaceId, TimeId, Memo";

		/*
		String sqlstr = "select Id, ContributeDate, Email, PlaceId, TimeId, Memo from Counter " +
		"where Email is null or Email == '' " +
		"order by Id " ;
		*/

		mcur = mdb.rawQuery(sqlstr, null);
		boolean isEof = mcur.moveToFirst();


		ArrayList<BindData> list = new ArrayList<BindData>();

		while(isEof){
			BindData data = new BindData();
			data.place = mcur.getString(1);
			data.time = mcur.getString(2);
			data.date = mcur.getString(0);
			data.memo = mcur.getString(3);
			list.add(data);

		  isEof = mcur.moveToNext();
		}

		mcur.close();

		mAdapter = new CounterAdapter(CounterActivity.this, list);
		mListView.setAdapter(mAdapter);

		// 空テキスト表示非表示
		mEmptyText.setVisibility(list.size() == 0 ? View.VISIBLE : View.GONE);
	}


	/**
	 * SDBからの初期化読み込みクラス
	 *
	 * @author noxi
	 *
	 */
	class SdbTask extends AsyncTask<Void, Void, String> {

		private ProgressDialog mProgressDialog;

		@Override
		protected void onPreExecute() {
			mProgressDialog = new ProgressDialog(CounterActivity.this);
			mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
			mProgressDialog.setMessage(CounterActivity.this.getString(R.string.m_run_processing));
			mProgressDialog.setCancelable(true);
			mProgressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
				@Override
				public void onCancel(DialogInterface dialog) {
					CounterActivity.this.finish();
				}
			});
			mProgressDialog.show();
		}

		/*
		 * SDBから情報を読み込めた場合はnullを返す
		 * それ以外はエラーメッセージを返す
		 *
		 * (non-Javadoc)
		 * @see android.os.AsyncTask#doInBackground(Params[])
		 */
		@Override
		@SuppressWarnings("unchecked")
		protected String doInBackground(Void... params) {

			String maxverno;
			String query;
			Class<?>[] classes;
			List<Base> masterlist;
			List<MasterVersion> versionlist;

			try {
				maxverno = mPref.getString(Constants.PREF_MASTER_VERSION, "0");

				// 現在保持しているマスターバージョンよりも更新されているかSDBへ問い合わせ
				query = "select * from " + Sdb.getDomainName(MasterVersion.class) + " where itemName() > '" + maxverno + "'";
				versionlist = (List<MasterVersion>) Sdb.selectQuery(Sdb.getSdb(CounterActivity.this), query, new MasterVersion());
				if(versionlist.size() > 0){
					classes = new Class[]{Place.class, Time.class, Occupation.class, Use.class};
					for(int i = 0;i < classes.length;i++){
						masterlist = (List<Base>) Sdb.selectQuery(Sdb.getSdb(CounterActivity.this),	"select * from " + Sdb.getDomainName(classes[i]) + " where DispOdr is not null ORDER BY DispOdr", (Base) classes[i].newInstance());
						for(int k = 0;k < masterlist.size();k++){
							mDatabase.save(mdb, masterlist.get(k));
						}
					}
					// prefのバージョンNoを更新する
					prefPutString(Constants.PREF_MASTER_VERSION, versionlist.get(versionlist.size() - 1).getId());
				}

				// 場所リストを取得する
				Common.setPlaceList((List<Place>) mDatabase.find(mdb, Place.class, null, null, "DispOdr"));

				// 時間リストを取得する
				Common.setTimeList((List<Time>) mDatabase.find(mdb, Time.class, null, null, "DispOdr"));

				// 職業リストを取得する
				Common.setOccList((List<Occupation>) mDatabase.find(mdb, Occupation.class, null, null, "DispOdr"));

				// 利用区分リストを取得する
				Common.setUseList((List<Use>) mDatabase.find(mdb, Use.class, null, null, "DispOdr"));

				return null;
			} catch (Exception e) {
				e.printStackTrace();
				return e.getMessage();
			}
		}

		@Override
		protected void onPostExecute(String result) {
			mProgressDialog.dismiss();

			// SDBからの読み込み失敗
			if (result != null) {
				Toast.makeText(CounterActivity.this, result, Toast.LENGTH_LONG).show();
				CounterActivity.this.finish();
			}
			// リスト作成
			else {
				createListFromDB();
			}
		}
	}

	/**
	 * @param key
	 * @param value
	 */
	private void prefPutString(String key, String value) {
		Editor editor = mPref.edit();
		editor.putString(key, value);
		editor.commit();
	}

	/**
	 * Googleアカウントの認証を促す確認メッセージを表示するダイアログのボタン押下時リスナー。
	 */
	private DialogInterface.OnClickListener authDialogListner = new DialogInterface.OnClickListener() {
		public void onClick(DialogInterface dialog, int which) {
			switch (which) {
			case DialogInterface.BUTTON1:
				startActivity(new Intent(CounterActivity.this, PrepareRequestTokenActivity.class));
				break;
			case DialogInterface.BUTTON2:
				finish();
				break;
			default:
				break;
			}
		}
	};

	/**
	 * CounterActivityのListViewで利用するアダプター
	 *
	 * @author noxi
	 *
	 */
	static class CounterAdapter extends BaseAdapter {

		protected Context mContext;
		protected LayoutInflater mInflater;
		protected ArrayList<BindData> mData;


		public CounterAdapter(Context context, ArrayList<BindData> data) {
			mContext = context;
			mData = data;

			mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		}

		public int getCount() {
			return mData.size();
		}

		public BindData getItem(int position) {
			return mData.get(position);
		}

		public long getItemId(int id) {
			return id;
		}

		public void removeItem(int position) {
			try {
				mData.remove(position);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		public View getView(int position, View convertView, ViewGroup parent) {

			// Viewの使い回しここから
			ViewHolder holder;
			if (convertView == null) {
				convertView = mInflater.inflate(R.layout.listitem_counter, parent, false);

				holder = new ViewHolder();
				holder.place = (TextView) convertView.findViewById(R.id.text_place);
				holder.time = (TextView) convertView.findViewById(R.id.text_time);
				holder.date = (TextView) convertView.findViewById(R.id.text_date);

				convertView.setTag(holder);
			} else {
				holder = (ViewHolder) convertView.getTag();
			}
			// Viewの使い回しここまで

			BindData data = mData.get(position);

			holder.place.setText("Place: " + Common.getPlaceList().get(data.place).getName());
			holder.time.setText("Time: " + Common.getTimeList().get(data.time).getName());
			holder.date.setText("Date: " + data.date);

			return convertView;
		}


		static final class ViewHolder {
			TextView place;
			TextView time;
			TextView date;
		}
	}

	/**
	 * ListViewに表示するクラス（サンプル用）
	 *
	 * @author noxi
	 *
	 */
	static class BindData {
		public String place;
		public String time;
		public String date;
		public String memo;
	}
}
